﻿using System;
using System.IO;
using System.Text;

using NUnit.Framework;

using Uhi.Libraries.Test;
using Uhi.Libraries.Test.Files;
using Uhi.Libraries.Windows.Interactivity;

using Uhi.Applications.FileAid.Interactivity;
using Uhi.Applications.FileAid.Model;
using Uhi.Applications.FileAid.ViewModel;

namespace FileAidTest.ViewModel
{
    [TestFixture]
    public class FileViewModelTest
    {
        #region Filename

        #region 正常ケース
        [Test]
        public void Filename_正常ケース()
        {
            var vm = new FileViewModel();
            vm.AsDynamic().records = new RecordViewModel[0];
            vm.Filename = "foo";

            vm.Filename.Is("foo");
            (vm.AsDynamic().records as RecordViewModel[]).IsNull();
        }
        #endregion

        #region 変更通知のテスト
        [Test]
        public void Filename_変更通知のテスト()
        {
            var vm = new FileViewModel();
            vm.TraceNotified(() => vm.Filename);
            vm.TraceNotified(() => vm.Records);

            vm.Filename = "foo";

            vm.Filename.Is("foo");
            vm.VerifyAllNotified();
        }
        #endregion

        #endregion

        #region Length

        #region 正常ケース
        [Test]
        public void Length_正常ケース()
        {
            var vm = new FileViewModel();
            vm.AsDynamic().records = new RecordViewModel[0];
            vm.Length = 100;

            vm.Length.Is(100);
            (vm.AsDynamic().records as RecordViewModel[]).IsNull();
        }
        #endregion

        #region 変更通知のテスト
        [Test]
        public void Length_変更通知のテスト()
        {
            var vm = new FileViewModel();
            vm.TraceNotified(() => vm.Length);
            vm.TraceNotified(() => vm.Records);
            vm.TraceNotified(() => vm.ColumnPositionLabel);

            vm.Length = 100;

            vm.Length.Is(100);
            vm.VerifyAllNotified();
        }
        #endregion

        #endregion

        #region Encoding

        #region 正常ケース
        [Test]
        public void Encoding_正常ケース()
        {
            var vm = new FileViewModel();
            vm.AsDynamic().records = new RecordViewModel[0];
            vm.Encoding = "Shift_JIS";

            vm.Encoding.Is("Shift_JIS");
            (vm.AsDynamic().records as RecordViewModel[]).IsNull();
        }
        #endregion

        #region 変更通知のテスト
        [Test]
        public void Encoding_変更通知のテスト()
        {
            var vm = new FileViewModel();
            vm.TraceNotified(() => vm.Encoding);
            vm.TraceNotified(() => vm.Records);

            vm.Encoding = "Shift_JIS";

            vm.Encoding.Is("Shift_JIS");
            vm.VerifyAllNotified();
        }
        #endregion

        #endregion

        #region AcceptReturn

        #region 正常ケース
        [Test]
        public void AcceptReturn_正常ケース()
        {
            var vm = new FileViewModel();
            vm.AsDynamic().records = new RecordViewModel[0];
            vm.AcceptReturn = true;

            vm.AcceptReturn.Is(true);
            (vm.AsDynamic().records as RecordViewModel[]).IsNull();
        }
        #endregion

        #region 変更通知のテスト
        [Test]
        public void AcceptReturn_変更通知のテスト()
        {
            var vm = new FileViewModel();
            vm.TraceNotified(() => vm.AcceptReturn);
            vm.TraceNotified(() => vm.Records);

            vm.AcceptReturn = true;

            vm.AcceptReturn.Is(true);
            vm.VerifyAllNotified();
        }
        #endregion

        #endregion

        #region Records

        #region 正常ケース
        [Test]
        public void Records_正常ケース()
        {
            var dir = Path.Combine(Path.GetTempPath(), "FileViewModelTest");
            var file = "foo.txt";
            var path = Path.Combine(dir, file);
            var txt = new Txt(dir, file, "aaaaabbbbbcccccdddddeeeee");

            using (txt)
            {
                txt.Setup();

                var vm = new FileViewModel();
                vm.Filename = path;
                vm.Length = 5;
                vm.Encoding = Encoding.UTF32.WebName;
                vm.AcceptReturn = false;

                var recs = vm.Records;

                recs.Length.Is(5);

                (recs[0].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[0].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[0].AsDynamic().RecordInfo as IRecordInfo).Line.Is(0);
                (recs[0].AsDynamic().Encode as Encoding).Is(Encoding.UTF32);

                (recs[1].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[1].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[1].AsDynamic().RecordInfo as IRecordInfo).Line.Is(1);
                (recs[1].AsDynamic().Encode as Encoding).Is(Encoding.UTF32);

                (recs[2].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[2].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[2].AsDynamic().RecordInfo as IRecordInfo).Line.Is(2);
                (recs[2].AsDynamic().Encode as Encoding).Is(Encoding.UTF32);

                (recs[3].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[3].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[3].AsDynamic().RecordInfo as IRecordInfo).Line.Is(3);
                (recs[3].AsDynamic().Encode as Encoding).Is(Encoding.UTF32);

                (recs[4].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[4].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[4].AsDynamic().RecordInfo as IRecordInfo).Line.Is(4);
                (recs[4].AsDynamic().Encode as Encoding).Is(Encoding.UTF32);
            }
        }
        #endregion

        #region 改行あり
        [Test]
        public void Records_改行あり()
        {
            var dir = Path.Combine(Path.GetTempPath(), "FileViewModelTest");
            var file = "foo.txt";
            var path = Path.Combine(dir, file);
            var txt = new Txt(dir, file, "a\r\nbbbbbcccccdddddeeeee");

            using (txt)
            {
                txt.Setup();

                var vm = new FileViewModel();
                vm.Filename = path;
                vm.Length = 5;
                vm.Encoding = Encoding.UTF8.WebName;
                vm.AcceptReturn = true;

                var recs = vm.Records;

                recs.Length.Is(5);

                (recs[0].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[0].AsDynamic().RecordInfo as IRecordInfo).Length.Is(3);
                (recs[0].AsDynamic().RecordInfo as IRecordInfo).Line.Is(0);
                (recs[0].AsDynamic().Encode as Encoding).Is(Encoding.UTF8);

                (recs[1].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[1].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[1].AsDynamic().RecordInfo as IRecordInfo).Line.Is(1);
                (recs[1].AsDynamic().Encode as Encoding).Is(Encoding.UTF8);

                (recs[2].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[2].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[2].AsDynamic().RecordInfo as IRecordInfo).Line.Is(2);
                (recs[2].AsDynamic().Encode as Encoding).Is(Encoding.UTF8);

                (recs[3].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[3].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[3].AsDynamic().RecordInfo as IRecordInfo).Line.Is(3);
                (recs[3].AsDynamic().Encode as Encoding).Is(Encoding.UTF8);

                (recs[4].AsDynamic().RecordInfo as IRecordInfo).Filename.Is(path);
                (recs[4].AsDynamic().RecordInfo as IRecordInfo).Length.Is(5);
                (recs[4].AsDynamic().RecordInfo as IRecordInfo).Line.Is(4);
                (recs[4].AsDynamic().Encode as Encoding).Is(Encoding.UTF8);
            }
        }
        #endregion

        #endregion

        #region ColumnPositionLabel

        #region 正常ケース
        [Test]
        public void ColumnPositionLabel_正常ケース()
        {
            var vm = new FileViewModel();
            vm.Length = 20;
            var expected =
                "         1         2" + "\r\n" +
                "12345678901234567890";
            vm.ColumnPositionLabel.Is(expected);
        }
        #endregion

        #endregion

        #region SelectedIndex

        #region 正常ケース
        [Test]
        public void SelectedIndex_正常ケース()
        {
            var vm = new FileViewModel();
            vm.SelectedIndex = 10;
            vm.SelectedIndex.Is(10);
        }
        #endregion

        #region 変更通知のテスト
        [Test]
        public void SelectedIndex_変更通知のテスト()
        {
            var vm = new FileViewModel();
            vm.TraceNotified(() => vm.SelectedIndex);

            vm.SelectedIndex = 10;

            vm.SelectedIndex.Is(10);
            vm.VerifyAllNotified();
        }
        #endregion

        #endregion

        #region OpenCommand

        #region 正常ケース
        [Test]
        public void OpenCommand_正常ケース()
        {
            var vm = new FileViewModel();
            vm.OpenCommand.Execute("foo");
            vm.Filename.Is("foo");
        }
        #endregion

        #endregion

        #region SaveCommand

        #region 上書き
        [Test]
        public void SaveCommand_上書き()
        {
            var dir = Path.Combine(Path.GetTempPath(), "FileViewModelTest");
            var file = "foo.txt";
            var path = Path.Combine(dir, file);
            var txt = new Txt(dir, file, "aaaaabbbbbcccccdddddeeeee");

            using (txt)
            {
                txt.Setup();

                var vm = new FileViewModel();
                vm.Filename = path;
                vm.Length = 5;
                vm.Encoding = Encoding.Default.WebName;

                vm.Records[2].Record = "33333";

                vm.SaveCommand.Execute(path);

                File.ReadAllText(path).Is("aaaaabbbbb33333dddddeeeee");
                vm.Filename.Is(path);
            }
        }
        #endregion

        #region 別名で保存
        [Test]
        public void SaveCommand_別名で保存()
        {
            var dir = Path.Combine(Path.GetTempPath(), "FileViewModelTest");
            var file1 = "foo.txt";
            var file2 = "bar.txt";
            var path1 = Path.Combine(dir, file1);
            var path2 = Path.Combine(dir, file2);
            var txt1 = new Txt(dir, file1, "aaaaabbbbbcccccdddddeeeee");
            var txt2 = new Txt(dir, file2, "foo");

            using (txt1)
            using (txt2)
            {
                txt1.Setup();
                txt2.Setup();

                var vm = new FileViewModel();
                vm.Filename = path1;
                vm.Length = 5;
                vm.Encoding = Encoding.Default.WebName;

                vm.Records[2].Record = "33333";

                vm.SaveCommand.Execute(path2);

                File.ReadAllText(path1).Is("aaaaabbbbbcccccdddddeeeee");
                File.ReadAllText(path2).Is("aaaaabbbbb33333dddddeeeee");
                vm.Filename.Is(path2);
            }
        }
        #endregion

        #endregion

        #region SearchCommand

        #region SearchText

        #region 正常ケース
        [Test]
        public void SearchText_正常ケース()
        {
            var vm = new FileViewModel();
            vm.AsDynamic().SearchText = "foo";
            vm.SearchText.Is("foo");
        }
        #endregion

        #region 変更通知のテスト
        [Test]
        public void SearchText_変更通知のテスト()
        {
            var vm = new FileViewModel();
            vm.TraceNotified(() => vm.SearchText);

            vm.AsDynamic().SearchText = "foo";

            vm.SearchText.Is("foo");
            vm.VerifyAllNotified();
        }
        #endregion

        #endregion

        #region 正常ケース
        [Test]
        public void SearchCommand_正常ケース()
        {
            var dir = Path.Combine(Path.GetTempPath(), "FileViewModelTest");
            var file = "foo.txt";
            var path = Path.Combine(dir, file);
            var txt = new Txt(dir, file, "aaaaabbbbbcccccaaaaabbbbbcccccaaaaabbbbbccccc");

            using (txt)
            {
                txt.Setup();

                var vm = new FileViewModel();
                vm.Filename = path;
                vm.Length = 15;
                vm.Encoding = Encoding.Default.WebName;

                vm.Trace<InteractionRequestEventArgs>("Requested", e =>
                    e.RequestId == "SelectText" &&
                    (e.EventData as TextSelection).SelectionRow == 0 &&
                    (e.EventData as TextSelection).SelectionColumn == 5 &&
                    (e.EventData as TextSelection).SelectionStart == 5 &&
                    (e.EventData as TextSelection).SelectionLength == 5
                );

                vm.SearchCommand.Execute("bbbbb");

                vm.SearchText.Is("bbbbb");
                vm.VerifyAllRaised();
            }
        }
        #endregion

        #region 途中から検索した場合
        [Test]
        public void SearchCommand_途中から検索した場合()
        {
            var dir = Path.Combine(Path.GetTempPath(), "FileViewModelTest");
            var file = "foo.txt";
            var path = Path.Combine(dir, file);
            var txt = new Txt(dir, file, "aaaaabbbbbcccccaaaaabbbbbcccccaaaaabbbbbccccc");

            using (txt)
            {
                txt.Setup();

                var vm = new FileViewModel();
                vm.Filename = path;
                vm.Length = 15;
                vm.Encoding = Encoding.Default.WebName;
                vm.SelectedIndex = 1;
                vm.Records[1].CaretIndex = 7;

                vm.Trace<InteractionRequestEventArgs>("Requested", e =>
                    e.RequestId == "SelectText" &&
                    (e.EventData as TextSelection).SelectionRow == 2 &&
                    (e.EventData as TextSelection).SelectionColumn == 5 &&
                    (e.EventData as TextSelection).SelectionStart == 5 &&
                    (e.EventData as TextSelection).SelectionLength == 5
                );

                vm.SearchCommand.Execute("bbbbb");

                vm.SearchText.Is("bbbbb");
                vm.VerifyAllRaised();
            }
        }
        #endregion

        #region 検索結果が見つからない場合
        [Test]
        public void SearchCommand_検索結果が見つからない場合()
        {
            var dir = Path.Combine(Path.GetTempPath(), "FileViewModelTest");
            var file = "foo.txt";
            var path = Path.Combine(dir, file);
            var txt = new Txt(dir, file, "aaaaabbbbbcccccaaaaabbbbbcccccaaaaabbbbbccccc");

            using (txt)
            {
                txt.Setup();

                var vm = new FileViewModel();
                vm.Filename = path;
                vm.Length = 15;
                vm.Encoding = Encoding.Default.WebName;

                vm.Trace<InteractionRequestEventArgs>("Requested", e =>
                    e.RequestId == "ShowMessage" &&
                    (e.EventData as string) == "\"foo\" が見つかりません"
                );

                vm.SearchCommand.Execute("foo");

                vm.SearchText.Is("foo");
                vm.VerifyAllRaised();
            }
        }
        #endregion

        #endregion

        #region FontFamily

        #region 正常ケース
        [Test]
        public void FontFamily_正常ケース()
        {
            var family = "font";
            var vm = new FileViewModel();
            vm.FontFamily = family;
            vm.FontFamily.Is(family);
        }
        #endregion

        #endregion

        #region FontSize

        #region 正常ケース
        [Test]
        public void FontSize_正常ケース()
        {
            var size = 12.0;
            var vm = new FileViewModel();
            vm.FontSize = size;
            vm.FontSize.Is(size);
        }
        #endregion

        #endregion

        #region FontStyle

        #region 正常ケース
        [Test]
        public void FontStyle_正常ケース()
        {
            var style = "style";
            var vm = new FileViewModel();
            vm.FontStyle = style;
            vm.FontStyle.Is(style);
        }
        #endregion

        #endregion

        #region FontWeight

        #region 正常ケース
        [Test]
        public void FontWeight_正常ケース()
        {
            var weight = "weight";
            var vm = new FileViewModel();
            vm.FontWeight = weight;
            vm.FontWeight.Is(weight);
        }
        #endregion

        #endregion

        #region Request

        #region 正常ケース
        [Test]
        public void Request_正常ケース()
        {
            var arg = new object();
            var callback = new Action(() => { });

            var vm = new FileViewModel();
            vm.Trace<InteractionRequestEventArgs>("Requested", e =>
                e.RequestId == "test" &&
                e.EventData == arg &&
                e.Callback == callback
            );

            vm.Request("test", arg, callback);
            vm.VerifyAllRaised();
        }
        #endregion

        #endregion
    }
}
